function selector(select, Aparent) {
  let parent = Aparent || document
  let realSelector
  if (select.indexOf('#') !== -1) {
    realSelector = select.slice(1)
    return parent.getElementById(realSelector)
  } else if (select.indexOf('.') !== -1) {
    realSelector = select.slice(1)
    return parent.querySelectorAll(realSelector)
  } else {
    return parent.getElementsByTagName(select)
  }
}
const canvas = selector('#canvas')
const ctx = canvas.getContext('2d')
ctx.globalCompositeOperation = 'source-atop'

const RATIO = 2

const tool = selector('#tool')
const toolHeight = tool.offsetHeight
let canvasOffset = canvas.getBoundingClientRect()
const canvasWidth = canvas.width = canvasOffset.width * RATIO
const canvasHeight = canvas.height = (canvasOffset.height - toolHeight) * RATIO
canvas.style.height = canvasHeight / RATIO + 'px'
canvasOffset = canvas.getBoundingClientRect()

let lastImageData = []

// 坐标转换 相对窗口坐标变为canvas实际坐标
function windowToCanvas(x, y) {
  return {
    x: (x - canvasOffset.left) * (canvasWidth / canvasOffset.width),
    y: (y - canvasOffset.top) * (canvasHeight / canvasOffset.height)
  }
}

// 获取鼠标canvas坐标
function getTouchPosition(e) {
  let touch = e.changedTouches[0]
  return windowToCanvas(touch.clientX, touch.clientY)
}
// 鼠标点击canvas坐标的对称点坐标
function getTouchPositionD(e) {
  let touch = e.changedTouches[0]
  var zb = windowToCanvas(touch.clientX, touch.clientY)
  return {
    x: canvasWidth - zb.x,
    y: zb.y
  }
}

// 储存画布信息（用于撤回）
function saveImageData(data) {
  (lastImageData.length == 5) && (lastImageData.shift())
  lastImageData.push(data)
}

// 工具基础 宽度，颜色，是否在绘画中，是否被选中
class Basic {
  constructor(width = RATIO, color = '#000') {
    this.width = width
    this.color = color
    this.drawing = false
    this.isSelect = false
  }
}

// 橡皮 颜色为背景色的铅笔，但是在对称变换的时候会有问题，以后会改成用clearRect来擦除
class Eraser extends Basic {
  constructor(width) {
    super(width, '#fff')
    this.name = 'eraser'
    this.dom = selector(`#${this.name}`)
  }
  begin(loc) {
    saveImageData(ctx.getImageData(0, 0, canvasWidth, canvasHeight))
    // 先保存画布状态，再改变画布状态
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.beginPath()
    ctx.moveTo(loc.x + 0.5, loc.y + 0.5)
  }
  draw(loc) {
    ctx.lineTo(loc.x + 0.5, loc.y + 0.5)
    ctx.stroke()
  }
  end(loc) {
    ctx.lineTo(loc.x + 0.5, loc.y + 0.5)
    ctx.stroke()
    // 恢复到之前的画布状态
    ctx.restore()
  }
  bindEvent() {
    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.drawing = true
      let loc = getTouchPosition(e)
      this.begin(loc)
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        this.draw(loc)
      }
    })
    canvas.addEventListener('touchend', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      let loc = getTouchPosition(e)
      this.end(loc)
      this.drawing = false
    })
  }
}

// 清空
class Clear extends Basic {
  constructor(width) {
    super(width, '#fff')
    this.name = 'clr'
    this.dom = selector(`#${this.name}`)
  }
  bindEvent() {
  }
}

// 中心对称
class Xuanzhuan extends Basic {
  //  问题线条  7 11  13  14  16  17
  constructor(width = RATIO, color = '#000') {
    super(width, color)
    this.name = 'xuanzhuan'
    this.dom = selector(`#${this.name}`)
  }
  getNum() {
    var num = 6;
    var sel = document.getElementById("zxdc"); //定位id
    var index = sel.selectedIndex; // 选中索引
    var num = sel.options[index].value; // 选中值
    return num
  }


  begin() {
    saveImageData(ctx.getImageData(0, 0, canvasWidth, canvasHeight))
    // 先保存画布状态，再改变画布状态
    ctx.save()
    ctx.lineWidth = this.width
    ctx.strokeStyle = this.color
    ctx.beginPath()
  }

  drawFn(op, num) {
    var deg = Math.floor(360 / num);
    var that = this
    for (var i = 0, l = 360; i < l; i += deg) {
      this.drawRotate(i / 180 * Math.PI, function (ctx) {
        that.draw(op);
      });
    }
  }
  drawRotate(deg, fn, _ctx) {
    _ctx = _ctx || ctx
    _ctx.save();
    _ctx.translate(canvas.width / 2, canvas.height / 2);
    _ctx.rotate(deg);
    fn && fn(_ctx);
    _ctx.restore();
  }
  draw(option, _ctx) {
    _ctx = _ctx || ctx;
    _ctx.beginPath();
    _ctx.moveTo(option.bx - canvas.width / 2, option.by - canvas.height / 2);
    _ctx.lineTo(option.ex - canvas.width / 2, option.ey - canvas.height / 2);
    _ctx.stroke();
  }

  bindEvent() {

    var num = this.getNum()

    var sel = document.getElementById("zxdc")
    var that = this
    sel.onchange = function () {
      num = that.getNum()
    }

    var dot = [
      // 鼠标点
      {
        bx: 0,
        by: 0,
        ex: 0,
        ey: 0,
      }
    ]

    canvas.addEventListener('touchstart', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      this.begin()
      this.drawing = true
      let loc = getTouchPosition(e)
      dot[0].ex = dot[0].bx = loc.x
      dot[0].ey = dot[0].by = loc.y
    })
    canvas.addEventListener('touchmove', (e) => {
      e.preventDefault()
      if (!this.isSelect) {
        return false
      }
      if (this.drawing) {
        let loc = getTouchPosition(e)
        let dloc = getTouchPositionD(e)
        dot[0].bx = dot[0].ex
        dot[0].by = dot[0].ey
        dot[0].ex = loc.x
        dot[0].ey = loc.y
        this.drawFn(dot[0], num)
      }
    })
  }
}

// 整合绘图工具
class Tool {
  constructor() {
    this.eraser = new Eraser(RATIO * 10)
    this.clr = new Clear()
    this.xuanzhuan = new Xuanzhuan()
    let allTools = [this.eraser, this.clr, this.xuanzhuan]
    // 设置watcher 改变工具时改变工具的isSelected属性
    Object.defineProperty(this, 'selected', {
      set: function (value) {
        for (let item of allTools) {
          if (value == 'zxdc') {
            value = 'xuanzhuan'
          }
          if (item.name === value) {
            item.isSelect = true
            if (value == 'eraser') {
              item.dom.style.boxShadow = '2px 2px  15px #333'
            }
          } else {
            item.isSelect = false
            item.dom.style.boxShadow = '0px 0px  0px #fff'
          }
        }
      },
      get: function () {
        for (let item of allTools) {
          if (item.isSelect) {
            return item.name
          }
        }
      }
    })
  }
  bindEvent() {
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);

    var isEraser = false;
    this.selected = 'xuanzhuan'
    tool.addEventListener('click', (e) => {
      let target = e.target
      let name = target.getAttribute('id')
      if (name !== 'clr') {
        this.selected = name
      }
      lineWidth.range.value = this[name].width / RATIO
      if (isEraser) {
        this.selected = 'xuanzhuan'
      }
      if (name === 'eraser') {
        isEraser = !isEraser
        return false
      }
      if (name === 'clr') {
        ctx.fillStyle = "#fff";
        ctx.fillRect(0, 0, canvasWidth, canvasHeight);
        return false
      }
      palette.entrance.style.color = this[name].color
    })
    this.eraser.bindEvent()
    this.xuanzhuan.bindEvent()
  }
}

//调色板
class Palette {
  constructor() {
    this.dom = selector("#Palette")
    this.entrance = selector("#toPalette")
    this.show = false
  }
  bindEvent() {
    this.dom.addEventListener('click', (e) => {
      const target = e.target
      if (target === this.entrance) {
        this.show = !this.show
        if (this.show) {
          this.dom.className = 'palette palette-show'
        } else {
          this.dom.className = 'palette'
        }
      } else if (target.className.indexOf('item') !== -1) {
        if (tools[tools.selected].name === 'eraser') {
          return false
        }
        const color = window.getComputedStyle(target, null).backgroundColor
        this.entrance.style.color = color
        tools[tools.selected].color = color
        this.dom.className = 'palette'
      }
    })
  }
}

//长度选择
class LineWidth {
  constructor() {
    this.dom = selector("#width")
    this.entrance = selector("#toWidth")
    this.range = selector("#lineWidth")
    this.show = false
  }
  bindEvent() {
    this.entrance.addEventListener('click', (e) => {
      this.show = !this.show
      if (this.show) {
        this.dom.className = 'width width-show'
      } else {
        this.dom.className = 'width'
      }
    })
    this.range.addEventListener('change', (e) => {
      const width = this.range.value
      tools[tools.selected].width = width * RATIO
      this.dom.className = 'width'
    })
  }
}

const tools = new Tool()
const palette = new Palette()
const lineWidth = new LineWidth()

lineWidth.bindEvent()
palette.bindEvent()
tools.bindEvent()

  ; (function (ctx) {
    selector("#cancel").addEventListener('click', () => {
      if (lastImageData.length < 1) return false
      ctx.putImageData(lastImageData[lastImageData.length - 1], 0, 0)
      lastImageData.pop()
    })
    selector("#saveImg").addEventListener('click', () => {
      handleSave();
      function handleSave() {
        //导出base64格式的图片数据
        var base64Data = canvas.toDataURL("image/jpeg", 0.5);
        //封装blob对象
        var blob = base64Data;
        //组装formdata
        var fd = new FormData();
        fd.append("fileName", "tupian0810.jpg");
        fd.append("fileData", blob);//fileData为自定义

        $.post({
          url: 'https://xcx.nanxuncn.cn/api/canvas/sketchpadaccs/base64',
          type: 'post',
          data: fd,
          contentType: false, // 注意这里应设为false
          processData: false,
          async: false,
          cache: false,
          success: function (data) {
            console.log(data)
            wx.miniProgram.navigateTo({
              url: '/pages/download/download?imgUrl=' + data,
              success: function () {
                console.log('success')
              },
              fail: function () {
                console.log('fail');
              },
              complete: function () {
                console.log('complete');
              }
            });
          },
          error: function (err) {
            console.log(err);
          }
        })
      };
    })
  })(ctx)